package cn.duyo.spring.aop.framework;

import cn.duyo.spring.aop.AdvisedSupport;
import org.aopalliance.intercept.MethodInterceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 基于 JDK 实现的代理类 (基于接口, 所以必须要有接口)
 * tips: InvocationHandler 是JDK原生的，当前类实现接口 InvocationHandler（不使用匿名类方式），则可以分离invoke方法
 *       aopalliance包是Java领域定义的AOP标准接口集
 *
 * @author du
 */
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {

    private final AdvisedSupport advised;

    public JdkDynamicAopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }

    @Override
    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), advised.getTargetSource().getTargetClass(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         * TODO 这里意思是如果命中了被拦截增强的方法，就使用 aopalliance 标准接口集的增强拦截方法 MethodInterceptor 来调用。
         *  若AOP表达式未命中表示不进行AOP增强，就不走增强逻辑，直接使用java原生的反射调用
         */
        if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
            // 命中切点：执行AOP Alliance的增强逻辑
            return advised.getMethodInterceptor().invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args));
        }
        // 未命中切点：执行JDK反射原生调用
        return method.invoke(advised.getTargetSource().getTarget(), args);
    }
}
